﻿using System;
using System.Collections.Generic;
using CPETwit.Data.Entity;
using CPETwit.Web.Business;
using CPETwit.Web.Service.Interface;
using System.Linq;
using Bitly;
using System.Text.RegularExpressions;
using Twitterizer;

namespace CPETwit.Web.Service.Implementation
{
    /// <summary>
    /// Service WCF de gestion des fonctionnalités de twitter.
    /// </summary>
    public class TwitterService : ITwitterService
    {
        #region Fields

        private readonly TweetBusiness _tweetBusiness;
        private readonly UtilisateurBusiness _userBusiness;
        private readonly MessageBusiness _messageBusiness;
        private readonly TagBusiness _tagBusiness;

        #endregion

        #region Constructors

        public TwitterService()
        {
            _tweetBusiness = new TweetBusiness();
            _userBusiness = new UtilisateurBusiness();
            _messageBusiness = new MessageBusiness();
            _tagBusiness = new TagBusiness();
        }

        #endregion

        #region Tweet

        /// <summary>
        /// Recherche de tous les tweets par Tag.
        /// </summary>
        /// <param name="tag"></param>
        /// <returns></returns>
        public IEnumerable<Tweet> GetAllTweetsByTag(string tag)
        {
            if (String.IsNullOrEmpty(tag))
            {
                return null;
            }
            else if (!tag.StartsWith("#"))
            {
                tag = String.Format("#{0}",tag);
            }

            return _tweetBusiness.GetAllTweetsRechercheParTag(tag);
        }

        /// <summary>
        /// Recherche de tous les tweets par texte. La recherche s'effectue sur le contenu
        /// du message du tweet.
        /// </summary>
        /// <param name="texte"></param>
        /// <returns></returns>
        public IEnumerable<Tweet> GetAllTweetsByText(string texte)
        {
            return _tweetBusiness.GetAllTweetsRechercheParTexte(texte);
        }

        public IEnumerable<Tweet> GetAllTweetsByPublisher(string texte)
        {
            return _tweetBusiness.GetAllTweetsByPublisher(texte);
        }

        public IEnumerable<Tweet> GetAllTweetsByUserId(long id)
        {
            return _tweetBusiness.GetAllTweetsByUserId(id);
        }

        /// <summary>
        /// Recherche des derniers tweets pour un utilisateur.
        /// </summary>
        /// <param name="user"></param>
        /// <returns></returns>
        public IEnumerable<Tweet> GetUserTimeline(User user)
        {
            return _tweetBusiness.GetUserTimeline(user);
        }
        public IEnumerable<Tweet> GetUserTimeline(string login)
        {
            User user = _userBusiness.GetUser(login);
            return GetUserTimeline(user);
        }

        public void SaveTweet(User user, string message, bool tweetOnTwitter)
        {
            //raccourcicement  des url du message
            string regex = @"((www\.|(http|https|ftp|news|file)+\:\/\/)[&#95;.a-z0-9-]+\.[a-z0-9\/&#95;:@=.+?,##%&~-]*[^.|\'|\# |!|\(|?|,| |>|<|;|\)])";
            string short_url = "";
            MatchCollection urls = Regex.Matches(message, regex);
            string value;
            string url;
            foreach (var item in urls)
            {
                value = item.ToString();
                if (!value.StartsWith("http://"))
                    url = "http://" + value;
                else
                    url = value;

                short_url = API.Bit("o_2uk0h10pm4", "R_a7381ce39820eb573ee5d00219da3d82", url, "Shorten");
                if (short_url == "")
                    short_url = value;
                message = message.Replace(value, short_url);
            }
            
            //sauvegarde du message
            Message m = _messageBusiness.SaveMessage(message);
            //récupération des tags
            string[] words = message.Split(' ');
            List<string> tags = new List<string>();
            foreach (var item in words)
            {
                if (item.StartsWith("#"))
                    tags.Add(item);
            }

            //sauvegarde des tags
            List<Tag> allTags = _tagBusiness.SaveTag(tags);
            //liaison tags / message
            _messageBusiness.SaveTag(m, allTags);
            // sauvegarde du tweet
            _tweetBusiness.SaveTweet(user, m);

            // Si l'on veut tweeter sur twitter.
            if (tweetOnTwitter)
                TweetOnTwitter(m);
        }

        private void TweetOnTwitter(Message message)
        {
            if (message == null) throw new ArgumentNullException("message");

            OAuthTokens tokens = new OAuthTokens();
            tokens.AccessToken = "193018450-1u0DdNwdauCG2KcdU8erclQqSqJyUEPK4Q7BimSt";
            tokens.AccessTokenSecret = "icacXfiuDJzIvcXjTDJJuzMC8PLeVCtityKsMx7R7S0";
            tokens.ConsumerKey = "7t9j6nsHxX6ct4SDSRIT8g";
            tokens.ConsumerSecret = "yiIcJqu2eaFEYospCt8p4MIbAw9Z6lSdGtJC8Zk";

            TwitterResponse<TwitterStatus> tweetResponse = TwitterStatus.Update(tokens, message.contenu + " #CPETwittMeet");
            if (tweetResponse.Result == RequestResult.Success)
            {
                // Tweet posted successfully!
                //throw new Exception("Envoyé");
            }
            else
            {
                // Something bad happened
                // throw new Exception("pas envoyé");
            }
        }

        public void ReTweet(User user, Tweet tweet, bool tweetOnTwitter)
        {
            _tweetBusiness.SaveReTweet(user, tweet);

            // Si l'on veut tweeter sur twitter.
            if (tweetOnTwitter)
                TweetOnTwitter(tweet.MessageProperty);
        }

        public void UndoReTweet(User user, Tweet tweet)
        {
            _tweetBusiness.UndoReTweet(user, tweet);
        }

        public IEnumerable<Tweet> getTweetFromId(long id)
        {
            return _tweetBusiness.getTweetFromId(id);
        }

        public IEnumerable<Tweet> getAllTweetsFromLoginOrMessage(string texte)
        {
            IEnumerable<Tweet> tmp;
            tmp = GetAllTweetsByText(texte);
            IEnumerable<Tweet> tmp2;
            tmp2 = GetAllTweetsByPublisher(texte);
            List<Tweet> res = new List<Tweet>();
            res.AddRange(tmp);
            res.AddRange(tmp2);
            return res.OrderByDescending(tweet => tweet.tweetdate);
        }
        #endregion

        #region User

        /// <summary>
        /// Recherche un utilisateur par son login.
        /// </summary>
        /// <param name="login"></param>
        /// <returns></returns>
        public User GetUser(string login)
        {
            return _userBusiness.GetUser(login);
        }


        public IEnumerable<User> GetUsersByText(string text)
        {
            return _userBusiness.GetUsersByText(text);
        }


        /// <summary>
        /// Indique si l'email en paramètre est valide (=non utilisé)
        /// </summary>
        /// <param name="email"></param>
        /// <returns></returns>
        public bool IsEmailValid(string email)
        {
            return _userBusiness.IsEmailValid(email);
        }

        public bool IsUserNameValid(string userName)
        {
            return _userBusiness.IsUserNameValid(userName);
        }

        /// <summary>
        /// Recherche les personnes qui se sont abonnées à un utilisateur.
        /// </summary>
        /// <param name="user"></param>
        /// <returns></returns>
        public IEnumerable<User> GetFollowers(User user)
        {
            return _userBusiness.GetFollowers(user);
        }

        public IEnumerable<User> GetUnFollowers(User user)
        {
            return _userBusiness.GetUnFollowers(user);
        }

        /// <summary>
        /// Recherche les personnes auquelles un utilisateur est abonné.
        /// </summary>
        /// <param name="user"></param>
        /// <returns></returns>
        public IEnumerable<User> GetPublishers(User user)
        {
            return _userBusiness.GetPublishers(user);
        }

        public IEnumerable<User> GetUnPublishers(User user)
        {
            return _userBusiness.GetUnPublishers(user);
        }

        /// <summary>
        /// Création d'un utilisateur.
        /// </summary>
        /// <param name="login"></param>
        /// <param name="password"></param>
        /// <param name="email"> </param>
        /// <returns></returns>
        public User CreateUser(string login, string password, string email)
        {
            // Pas de duplication des emails & pseudos en base.
            User userCreated = null;
            if (_userBusiness.IsEmailValid(email) && _userBusiness.IsUserNameValid(login))
                userCreated = _userBusiness.createUser(login, password, email);
            return userCreated;
        }

        /// <summary>
        /// Suppression d'un utilisateur.
        /// </summary>
        /// <param name="login"></param>
        /// <param name="password"></param>
        /// <returns></returns>
        public bool DeleteUser(string login, string password)
        {
            return _userBusiness.deleteUser(login);
        }

        /// <summary>
        /// Mise à jour de l'utilisateur;
        /// </summary>
        /// <param name="u"></param>
        public void UpdateUser(User u)
        {
            _userBusiness.updateUser(u);
        }

        public IEnumerable<User> GetTweetOwner(Tweet t)
        {
            return _userBusiness.GetTweetOwner(t);
        }

        public IEnumerable<User> RechercheUser(Dictionary<string, string> filtres)
        {
            return _userBusiness.RechercheUser(filtres);
        }

        public void Follow(User follower, User publisher)
        {
            _userBusiness.Follow(follower, publisher);
        }

        public void Unfollow(User follower, User publisher)
        {
            _userBusiness.Unfollow(follower, publisher);
        }

        #endregion

    }
}
